package com.treehouse.url.farmer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;

import com.treehouse.logging.Logger;
import com.treehouse.pornstar.Pornstar;
import com.treehouse.scene.Scene;
import com.treehouse.url.HTMLParser;
import com.treehouse.url.farmer.pornstardetailedinformationgetter.IPornstarDetailedInformationGetter;
import com.treehouse.url.farmer.pornstardetailedinformationgetter.PornstarDetailedInformationGetter;
import com.treehouse.url.farmer.pornstarpagelinkgetter.IPornstarPageLinkGetter;
import com.treehouse.url.farmer.pornstarpagelinkgetter.PornstarPageLinkGetter;

public class URLFarmer implements IURLFarmer {
	private URL startURL = null;
	private URL homeURL = null;
	private int starCounter = 0;
	private int sceneCounter = 0;
	private IPornstarPageLinkGetter pageLinkGetter = new PornstarPageLinkGetter();
	private IPornstarDetailedInformationGetter detailedInformationGetter = new PornstarDetailedInformationGetter();
	private HTMLParser parser;

	public URLFarmer(String startURL, String homeURL, HTMLParser parser) {
		try {
			this.startURL = new URL(startURL);
			this.homeURL = new URL(homeURL);
			this.parser = parser;
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}

	public URL getStartURL() {
		return startURL;
	}

	public void setStartURL(URL startURL) {
		this.startURL = startURL;
	}

	public URL getHomeURL() {
		return homeURL;
	}

	public void setHomeURL(URL homeURL) {
		this.homeURL = homeURL;
	}

	public int getStarCounter() {
		return starCounter;
	}

	public void setStarCounter(int starCounter) {
		this.starCounter = starCounter;
	}

	public int getSceneCounter() {
		return sceneCounter;
	}

	public void setSceneCounter(int sceneCounter) {
		this.sceneCounter = sceneCounter;
	}

	public void postStats() {
		Logger.inf("Pornstars: " + starCounter + ".");
		Logger.inf("Scenes: " + sceneCounter + ".");
	}

	public LinkedList<Pornstar> getPornstarList() {
		LinkedList<Pornstar> list = new LinkedList<Pornstar>();
		LinkedList<URL> pages = new LinkedList<URL>();
		pages.add(this.startURL);
		URL url = this.startURL;

		boolean endOfPages = false;
		try {
			Logger.inf("Reading in PageLinks for PornstarList..");
			Logger.inf(this.startURL.toString());
			while (!endOfPages) {
				BufferedReader in = new BufferedReader(new InputStreamReader(
						url.openStream()));
				String inputLine = "";
				boolean found = false;
				while ((inputLine = in.readLine()) != null) {
					inputLine = this.parser.decodeHTML(inputLine);
					// Find Line for next Pornstarsite
					if (this.pageLinkGetter.containsNextLink(inputLine)) {
						// Get URL out of Line
						String link = this.pageLinkGetter
								.getLinkForLinkLine(inputLine);
						Logger.inf(homeURL + link);
						url = new URL(homeURL + link);
						pages.add(url);
						found = true;
						break;

					}
				}
				if (!found)
					endOfPages = true;
				in.close();

			}
			for (URL el : pages) {
				LinkedList<Pornstar> newList = this.getPornstarListFromPage(el);
				for (Pornstar star : newList) {
					list.add(star);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		this.postStats();
		return list;
	}

	public LinkedList<Pornstar> getPornstarListFromPage(URL page) {
		LinkedList<Pornstar> list = new LinkedList<Pornstar>();
		BufferedReader in;
		try {
			in = new BufferedReader(new InputStreamReader(page.openStream()));
			String inputLine;
			while ((inputLine = in.readLine()) != null) {
				inputLine = this.parser.decodeHTML(inputLine);
				if (inputLine.equals("\t<div class='gray'>")) {
					String nextLine = in.readLine();
					String home = nextLine.split("'")[1];
					String name = nextLine.split("class='name'>")[1]
							.split("</a>")[0];
					String rating = "";
					home = home
							.replaceAll("index.php", this.homeURL.toString());
					Logger.inf("Name: " + name);
					Logger.inf("Home: " + home);

					boolean ratingFound = false;
					while (!ratingFound) {
						String next = in.readLine();
						String[] nextSplit = next.split("class=\"info\">");
						if (nextSplit.length > 1) {
							rating = nextSplit[1];
							rating = rating.split("<span>")[0];
							if (rating.equals("Rating:")) {
								rating = next.split("<span>")[1]
										.substring(0, 3);
								ratingFound = true;
							}
						}

					}
					Logger.inf("Rating: " + rating);
					final Pornstar pornstar = new Pornstar();
					pornstar.setName(name);
					pornstar.setHome(new URL(home));

					rating = rating.replaceAll("\\)", "");
					rating = rating.replaceAll("\\(", "");
					pornstar.setRating(Double.parseDouble(rating));
					new Thread() {
						public void run() {
							getDetailedInformationForActor(pornstar);
						}
					}.start();
					starCounter++;
					list.add(pornstar);
				}
			}
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return list;
	}

	public Pornstar getDetailedInformationForActor(Pornstar actor) {
		URL home = actor.getHome();
		if (home == null) {
			Logger.err("Home URL of actor " + actor.getName()
					+ " is null, could not retrieve detailed information.");
			return actor;
		}
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(
					home.openStream()));
			String inputLine;
			boolean notEnd = true;
			while ((inputLine = in.readLine()) != null && notEnd) {
				inputLine = this.parser.decodeHTML(inputLine);
				if (this.detailedInformationGetter
						.isStartIntervalLine(inputLine)) {
					String biography = in.readLine();
					while (!biography.contains("</p>")) {
						biography = biography + in.readLine();
					}
					biography = biography.split("</p>")[0];
					biography = biography.replaceAll("<p>", "");
					biography = biography.replaceAll("<p class='description'>", "");
					biography = biography.trim();
					actor.setDescription(biography);
					notEnd = false;
				}
			}
		} catch (IOException e) {
			Logger.err("Could not retrieve detailed information for actor "
					+ actor.getName() + ".");
			Logger.err("Reason: " + e.getMessage());
		}

		return actor;
	}

	public LinkedList<Scene> lookupSceneList(Pornstar pornstar) {
		LinkedList<Scene> list = new LinkedList<Scene>();
		LinkedList<URL> pages = new LinkedList<URL>();
		URL url = pornstar.getHome();
		pages.add(url);

		boolean endOfPages = false;
		try {
			Logger.inf("Reading in Scenes for " + pornstar.getName() + "..");
			while (!endOfPages) {
				BufferedReader in = new BufferedReader(new InputStreamReader(
						url.openStream()));
				String inputLine = "";
				boolean found = false;
				while ((inputLine = in.readLine()) != null) {
					inputLine = this.parser.decodeHTML(inputLine);
					if (inputLine.contains("span class=\"next_prev\"")
							&& inputLine.contains(">next</a>")) {
						String[] splitted = inputLine.split("href=\"")[1]
								.split("\">");
						String link = splitted[0];

						Logger.inf(homeURL + link);
						url = new URL(homeURL + link);
						pages.add(url);
						found = true;
						break;

					}
				}
				if (!found)
					endOfPages = true;
				in.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		for (URL el : pages) {
			LinkedList<Scene> newList = this.getSceneListForPornstarPage(el);
			for (Scene scene : newList) {
				list.add(scene);
			}
		}

		return list;
	}

	public LinkedList<Scene> getSceneListForPornstarPage(URL url) {
		LinkedList<Scene> scenes = new LinkedList<Scene>();
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(
					url.openStream()));
			String inputLine = "";
			while ((inputLine = in.readLine()) != null) {
				inputLine = this.parser.decodeHTML(inputLine);

				if (inputLine
						.contains("<div class=\"full_width one_line wide_box_title\">")) {
					String next = in.readLine();
					String link = next.split("href=\"")[1].split("\"")[0];
					link = this.parser.decodeHTML(link);
					String title = in.readLine().split("</a>")[0].trim();
					Logger.inf(title);
					Logger.inf(this.homeURL + link);
					Scene scene = new Scene();
					scene.setTitle(title);
					scene.setUrl(new URL(this.homeURL.toString() + link));
					sceneCounter++;
					scenes.add(scene);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return scenes;
	}
}
